/* EasyWay Game Engine
 * Copyright (C) 2007 Daniele Paggi.
 *  
 * Written by: 2007 Daniele Paggi<dshnt@hotmail.com>
 *   
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details.
 * 
 * You should have received a copy of the GNU Library General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
package org.easyway.editor.analyzer;

import java.awt.Color;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;

import javassist.Modifier;

import javax.swing.JLabel;

import org.easyway.annotations.editor.Creator;
import org.easyway.annotations.editor.UEditor;
import org.easyway.editor.forms.components.Button;
import org.easyway.editor.forms.components.extended.ConstructorButton;
import org.easyway.editor.forms.components.extended.StaticMethodButton;
import org.easyway.optimizer.InitOptimizer;

public class Analyzer {

	public static String packages[] = { "org" };

	public static ArrayList<String> classes = InitOptimizer.classes;

	public static ArrayList<Class> uEditorClasses = new ArrayList<Class>(300);

	public static ArrayList<String> uEditorClassesName = new ArrayList<String>(
		300);

	/**
	 * search the classes that contains the UEditor annotation
	 */
	public static final void searchUEditor() {
		if (classes == null)
			return;
		Annotation[] annotations;
		Class tclass;
		String name;
		for (String s : classes) {
			try {
				tclass = ClassLoader.getSystemClassLoader().loadClass(s);
				annotations = tclass.getAnnotations();
				for (Annotation a : annotations) {
					if (a instanceof UEditor) {
						// System.out.println("FOUND >>> " + s);
						uEditorClasses.add(tclass);
						if ((name = ((UEditor) a).value()).equals("")) {
							uEditorClassesName.add(tclass.getSimpleName());
						} else {
							uEditorClassesName.add(name);
						}
						break;
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		InitOptimizer.classes = classes = null;
	}

	/**
	 * add the classes that contains the UEditor annotation to the Left Panel
	 * 
	 */
	public static final void addUEditorClasses() {
		// for (final Class tclass : uEditorClasses) {
		for (int index = uEditorClasses.size() - 1; index >= 0; --index) {
			final Class tclass = uEditorClasses.get(index);
			new Button(null, uEditorClassesName.get(index)) {

				private static final long serialVersionUID = -4659740024714546810L;

				public void command() {
					removeFromLPanel();
					searchConstructors(tclass);
					searchStaticMethods(tclass);
				}
			};
		}
	}

	/**
	 * search in a class the annotation Method<br>
	 * if the class contain the annotation Method will be added the relative
	 * Button in the LeftPanel
	 * 
	 * @param tlcass
	 */
	public static final void searchStaticMethods(Class tclass) {
		// all the methods of the class
		Method[] methods = tclass.getMethods();
		// all the annotations contained in the methods
		Annotation annotations[];
		for (final Method meth : methods) {
			annotations = meth.getAnnotations();
			for (Annotation ann : annotations) {
				if (ann instanceof org.easyway.annotations.editor.Method) {
					addStaticMethod(meth,(org.easyway.annotations.editor.Method)ann);
					continue;
				}
			}
		}

	}
	
	public static final StaticMethodButton addStaticMethod(Method meth) {
		return addStaticMethod(meth, null);		
	}


	public static final StaticMethodButton addStaticMethod(Method meth,org.easyway.annotations.editor.Method ann) {

		// annotations of parameters
		Annotation paramsAnn[][];
		// parameters
		Class params[];
		if (!Modifier.isStatic(meth.getModifiers()))
			return null;
		paramsAnn = meth.getParameterAnnotations();
		params = meth.getParameterTypes();
		return new StaticMethodButton(meth, paramsAnn, params,
			(org.easyway.annotations.editor.Method) ann);
	}

	/**
	 * search in a class the annotation Method<br>
	 * if the class contain the annotation Method will be added the relative
	 * Button in the LeftPanel
	 * 
	 * @param tlcass
	 */
	public static final void searchMethods(Class tclass) {
		// all the methods of the class
		Method[] methods = tclass.getMethods();
		// all the annotations contained in the methods
		Annotation annotations[];
		// annotations of parameters
		Annotation paramsAnn[][];
		// parameters
		Class params[];
		Class old = null;
		for (final Method meth : methods) {
			Class cls = meth.getDeclaringClass();
			if (Modifier.isStatic(meth.getModifiers()))
				continue;
			annotations = meth.getAnnotations();

			for (Annotation ann : annotations) {
				if (ann instanceof org.easyway.annotations.editor.Method) {
					paramsAnn = meth.getParameterAnnotations();
					params = meth.getParameterTypes();
					if (cls != old) {
						addSeparator(cls.getSimpleName());
						old = cls;
					}
					new StaticMethodButton(meth, paramsAnn, params,
						(org.easyway.annotations.editor.Method) ann);
				}
			}
		}

	}


	/**
	 * search in a class the annotation Creator<br>
	 * if the class contain the annotation Creator will be added the relative
	 * Button in the LeftPanel
	 * 
	 * @param tclass
	 *            the class in witch search the annoatation
	 */
	public static final void searchConstructors(Class tclass) {
		// all the construcotr of the class
		Constructor<?>[] constructors = tclass.getConstructors();
		// annotations contained in the constructor
		Annotation annotations[];
		// annotations of parameters
		Annotation paramsAnn[][];
		// parameters
		Class params[];
		addSeparator(tclass.getSimpleName());
		for (final Constructor con : constructors) {
			annotations = con.getAnnotations();

			for (Annotation ann : annotations) {
				if (ann instanceof Creator) {
					paramsAnn = con.getParameterAnnotations();
					params = con.getParameterTypes();
					new ConstructorButton(con, paramsAnn, params, (Creator) ann);
				}
			}
		}

	}
	
	public final static ConstructorButton addConstructor(Constructor con) {
		return addConstructor(con,null);
	}	
	
	public final static ConstructorButton addConstructor(Constructor con, Annotation ann) {
		Annotation paramsAnn[][] = con.getParameterAnnotations();
		Class params[] = con.getParameterTypes();
		return new ConstructorButton(con, paramsAnn, params, (Creator) ann);		
	}

	public static final void removeFromLPanel() {
		org.easyway.editor.forms.UEditor.getLeftPanel().removeAll();
		org.easyway.editor.forms.UEditor.getLeftPanel().repaint();
		// new LoaderButton("label","id");
	}

	public static final void addSeparator(String name) {
		JLabel label = new JLabel(name);
		label.setForeground(new Color(0, 0, 255));
		org.easyway.editor.forms.UEditor.getLeftPanel().add(label);
	}

}
